package com.analyse.stock.strategy.indicator;

import org.ta4j.core.BarSeries;
import org.ta4j.core.Indicator;
import org.ta4j.core.indicators.helpers.ClosePriceIndicator;
import org.ta4j.core.indicators.helpers.HighPriceIndicator;
import org.ta4j.core.indicators.helpers.LowPriceIndicator;
import org.ta4j.core.num.Num;

/**
 * 自定义 KDJ 指标实现
 */
public class KDJIndicator implements Indicator<Num> {
    private final Indicator<Num> rsvIndicator; // RSV 指标
   // private final int barCount; // 周期
    private Num prevK; // 上一个 %K 值
    private Num prevD; // 上一个 %D 值

    public KDJIndicator(Indicator<Num> closePrice, Indicator<Num> highPrice, Indicator<Num> lowPrice, int barCount) {
        this.rsvIndicator = new RSVIndicator(closePrice, highPrice, lowPrice, barCount);
        this.prevK = null;
        this.prevD = null;
    }

    // 定义指标
    public KDJIndicator(BarSeries series, int barCount){
        this(new ClosePriceIndicator(series), new HighPriceIndicator(series),new LowPriceIndicator(series),barCount);
    }

    @Override
    public Num getValue(int index) {
        // 计算 %K 值
        Num kValue = getK(index);
        // 计算 %D 值
        Num dValue = (prevD == null)
                ? kValue // 初始化 %D 值为 %K
                : prevD.multipliedBy(numOf(2.0 / 3.0)).plus(kValue.multipliedBy(numOf(1.0 / 3.0)));
        // 更新历史值
        prevK = kValue;
        prevD = dValue;
        // 返回 %D 值（可选返回 %K 或 %D）
        return dValue; // 或 return kValue;
    }

    public Num getD(int index) {
        return getValue(index);
    }
    public Num getK(int index) {
        Num rsv = rsvIndicator.getValue(index);
        // 计算 %K 值
        Num kValue = (prevK == null)
                ? rsv // 初始化 %K 值为 RSV
                : prevK.multipliedBy(numOf(2.0 / 3.0)).plus(rsv.multipliedBy(numOf(1.0 / 3.0)));
        // 更新历史值
        prevK = kValue;
        // 返回 %D 值（可选返回 %K 或 %D）
        return kValue; // 或 return kValue;
    }

    @Override
    public org.ta4j.core.BarSeries getBarSeries() {
        return rsvIndicator.getBarSeries();
    }

    @Override
    public Num numOf(Number number) {
        return null;
    }

    private Num numOf(double value) {
        return rsvIndicator.getBarSeries().numOf(value);
    }
}
